/** Class of universal functions - There are many classes universal
* to local.java and global.java. Let's have them here to prevent replication'
* @Aughor Hussein Patwa
* @Date 13 March 2007
*/ 

import java.util.*;
import java.lang.Double;

@SuppressWarnings("all")
public class Functions{
 
    double getCorrelationCoefficient(TreeMap obsPred){
	    double sigmaX = sigmaX(obsPred.keySet());
	    double sigmaX2 = sigmaXSquare(obsPred.keySet());
	    double sigmaY = sigmaY(obsPred.values());
	    double sigmaY2 = sigmaYSquare(obsPred.values());
	    double sigmaXY = sigmaXY(obsPred);
	    double numerator = (obsPred.size()*sigmaXY) - (sigmaX*sigmaY);
	    double denominator = Math.sqrt(((obsPred.size()*sigmaX2)-Math.pow(sigmaX,2)))*Math.sqrt(((obsPred.size()*sigmaY2)-Math.pow(sigmaY,2)));
	    return numerator/denominator;
	}

	TreeMap getRegressionPredictions(TreeMap pathObs){
	    TreeMap rtn = new TreeMap();
	    double sigmaX = sigmaX(pathObs.keySet());
	    double sigmaX2 = sigmaXSquare(pathObs.keySet());
	    double sigmaY = sigmaY(pathObs.values());
	    double sigmaXY = sigmaXY(pathObs);
	    double slope = getLeastSquareSlope(sigmaX,sigmaX2,sigmaY,sigmaXY,pathObs.size());//compute the slope with sign
	    double constantC = getLeastSquareC(sigmaX,sigmaX2,sigmaY,sigmaXY,pathObs.size());
	    for(Iterator i=pathObs.entrySet().iterator();i.hasNext();){
	        Map.Entry e = (Map.Entry)i.next();
	        Double key = (Double)e.getKey();
	        double predictedVal = slope*key.doubleValue()+constantC;
	        rtn.put(key,new Double(predictedVal));
	    }
	    return rtn;
	}

	double getCorrelation(){
	    //to be implemented
	    return 0;
	}

	static public double sigmaX(Set dateSet){
	    double rtn = 0;
	    int j = 0;
	    Double first = new Double(0);
	    for(Iterator i = dateSet.iterator();i.hasNext();){
	        Double key = (Double)i.next();
	        if(j==0)
	            first = key;
	        rtn = rtn + (key.doubleValue()-first.doubleValue());
	        j++;
	    }
	    return rtn;
	}

	static public double sigmaXSquare(Set dateSet){
	double rtn = 0;
	int j = 0;
	Double first = new Double(0);
	for(Iterator i = dateSet.iterator();i.hasNext();){
	    Double key = (Double)i.next();
	    if(j==0)
	        first = key;
	    rtn = rtn + Math.pow((key.doubleValue()-first.doubleValue()),2);
	    j++;
	}
	return rtn;
	}



	static public double sigmaY(Collection values){
	double rtn = 0;
	for(Iterator i = values.iterator();i.hasNext();){
	    Double ctVal = (Double)i.next();
	    rtn = rtn + ctVal.doubleValue();
	}
	return rtn;
	}


	static public double sigmaYSquare(Collection values){
	double rtn = 0;
	for(Iterator i = values.iterator();i.hasNext();){
	    Double ctVal = (Double)i.next();
	    rtn = rtn + Math.pow(ctVal.doubleValue(),2);
	}
	return rtn;
	}

	static public double sigmaXY(TreeMap series){
	double rtn = 0;
	Double first = (Double)series.firstKey();
	for(Iterator i = series.entrySet().iterator();i.hasNext();){
	    Map.Entry e = (Map.Entry) i.next();
	    Double key = (Double)e.getKey();
	    Double ctVal = (Double)e.getValue();
	    rtn = rtn + ((key.doubleValue()-first.doubleValue())*ctVal.doubleValue());
	}
	return rtn;
	}


	public static double  getLeastSquareSlope(double sigX,double sigX2,double sigY,double sigXY, int N){
	double num = ((N*sigXY) - (sigX*sigY));
	double den = ((N*sigX2) - Math.pow(sigX,2));
	return num/den;
	}

	public static double  getLeastSquareC(double sigX,double sigX2,double sigY,double sigXY,int N){
	double num = ((sigX2*sigY) - (sigXY*sigX));
	double den = ((N*sigX2) - Math.pow(sigX,2));
	return num/den;
	}
    
}